#ifndef PARSER_H
#define PARSER_H

#define MAIN_NAME "main"

class Function {
public: 
	struct Var {
		string  _name;
		int     _size;
	};

	struct Jump {
		int    _start;
		int    _end;
	};

public:
	Function() {}
	Function(const string &name) : _name(name) {}
	const string& getName() const { return _name; }
	bool addSymbol(const string &symbol, int size = 1);
	bool addParam(const string &param);
	bool isVar(const string &name);
	void addInstr(const char *fmt, ...); 
	void codeEmit(FILE *fp, char space = '\t');
	void push_loop(int i, int j);
	void pop_loop();
	int  peek_s_loop();
	int  peek_e_loop();

private:
	string         _name;
	vector<Var>    _symbolArray;
	vector<string> _paramArray;
	vector<string> _instrArray;	
	vector<Jump>    _loopStack;
};


class Parser {
public:
	Parser() :_currFun (NULL), _blockLevel(0) { memset(spaceBuf, 0, sizeof(spaceBuf)); }
	bool parseSourceCode(const char *filename);
	void parseStatement();
	void parseBlock();
	void parseFunc();
	void parseVar();
	void parseExpr();
	void parseSubExpr();
	void parseTerm();
	void parseFactor();
	void parseAssign();
	void parseReturn();
	void parseWhile();
	void parseBreak();
	void parseContinue();
	void parseIf();

	void codeEmit(const char *file);

	
	void readToken(Token token);

private:
	bool isFunc(const string &name);
	bool addFunc(const string &name);
	int  nextJumpIndex() { return ++_JumpIndex; }
	void ExitOnCodeError(const char *fmt, ...);

private:
	Lex   _lex;
	map<string, Function> _functions;
	Function             *_currFun;
	Function              _globalScope;
	int                   _blockLevel;
	char                  spaceBuf[64];
	
	static int   _JumpIndex;
	static const int _GLOBAL_SCOPE = -1;
};


#endif
